/**
 *
 */
package Control;

import Acquaintance.IACluster;
import Acquaintance.IAHouse;
import Acquaintance.IAUser;
import DALFactory.IDALFactory;
import DALFactory.IDataMapper;
import Entity.EHouse;
import Entity.EUser;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.TreeMap;

/**
 * 缓存类，采用单例模式中的影子模式 唯一获取缓存的方法是getCache 其他类无法实例化缓存类 缓存类用自身实例化
 *
 * @author kocio
 */
public final class CCache {

    private static CCache instance = null;
    private HashMap<String, IAUser> UserMap = null;
    private HashMap<String, IAHouse> HouseMap = null;
    private HashMap<Integer, IACluster> ChildenMap = null;
    private TreeMap<Integer, IACluster> ParentMap = null;
    private CConfig config;
    private IDALFactory IDALfactory;
    private IDataMapper IdataMapper;
    private String TargetDatabase;

    /**
     * 缓存构造函数
     */
    private CCache() {
        config = CConfig.getConfig();

      //  TargetDatabase = config.getProperties().get("Database").toString();
       TargetDatabase="MongoDAL.MongodbFactory";

        try {
            Class obj = Class.forName(TargetDatabase);
            IDALfactory = (IDALFactory) obj.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("缓存动态加载数据库抽象工程失败");
        }
        IdataMapper = IDALfactory.CreateDataMapper();
        this.UserMap = IdataMapper.getUserMap();
        this.HouseMap = IdataMapper.getHouseMap();
        if (IDALfactory.CreateDataProcess().ClusterIsEmty()) {
            this.ChildenMap = new HashMap<Integer, IACluster>();
            this.ParentMap = new TreeMap<Integer, IACluster>();
        } else {
            this.ChildenMap = IDALfactory.CreateDataProcess().getChildenMap();
            this.ParentMap = IDALfactory.CreateDataProcess().getParentMap();
        }
    }

    /**
     * 缓存类实例同步初始化
     */
    private static synchronized void syncInit() {
        if (instance == null) {
            instance = new CCache();
        }
    }

    /**
     * 获取缓存对象引用
     *
     * @return 缓存对象
     */
    public static CCache getCache() {
        syncInit();
        return instance;
    }

    /**
     * 获取EHouse的HashMap Key为ObjectID（“HID”+HID） Value为EHouse对象
     *
     * @return EHouse HashMap
     */
    public HashMap getHouseMap() {
        return HouseMap;
    }

    /**
     * 获取EUser的HashMap Key为ObjectID（“UID”+UID） Value为User对象
     *
     * @return EUser HashMap
     */
    public HashMap getUserMap() {
        return UserMap;
    }

    /**
     * 将缓存中的数据映射到数据库中
     */
    public void updateHashMap() {
        Collection c1 = this.HouseMap.values();
        Iterator it = c1.iterator();
        while (it.hasNext()) {
            EHouse house = (EHouse) it.next();
            if (house.isDirty()) {
                IdataMapper.updateHouse(house);
                house.setDirty(false);
            }
        }
        Collection c2 = this.UserMap.values();
        Iterator it2 = c2.iterator();
        while (it2.hasNext()) {
            EUser user = (EUser) it2.next();
            if (user.isDirty()) {
                IdataMapper.updateUser(user);
                user.setDirty(false);
            }
        }
    }

    /**
     * 新建用户在缓存中注册
     *
     * @param u 新建用户
     * @return True表明新建用户在缓存中注册成功 False表明新建用户在缓存中注册失败
     */
    public boolean registerUser(IAUser u) {
        if (this.UserMap.containsValue(u)) {
            return false;// 应该抛出自定义异常；
        } else {
            this.UserMap.put(u.getUserName(), u);
            return true;
        }
    }

    /**
     * 从缓存中移除EUser对象
     *
     * @param UserName
     */
    public void removeUser(String UserName) {
        this.UserMap.remove(UserName);
    }

    /**
     * 在缓存中注册新的房屋
     *
     * @param h 翻屋实体
     * @return True表明新建翻屋在缓存中注册成功 False表明新建翻屋在缓存中注册失败
     */
    public boolean registerHouse(IAHouse h) {
        if (this.HouseMap.containsValue(h)) {
            return false;// 应该抛出自定义异常；
        } else {
            this.HouseMap.put("HID" + h.getHID(), h);
            return true;
        }
    }

    /**
     * 从缓存中移除房屋实体
     *
     * @param hID 房屋ID
     */
    public void removeHouse(int hID) {
        this.HouseMap.remove(hID);
    }

    /**
     * 获取实例化缓存的该数据工厂
     *
     * @return 数据工厂
     */
    public IDALFactory getDALFactory() {
        return IDALfactory;
    }

    /**
     * 往缓存中注册聚类的子节点
     *
     * @param cluster 聚类子节点
     * @return true 表明删除成功 <br> false 表明删除失败 <br>
     */
    public boolean registerChilden(IACluster cluster) {
        if (this.ChildenMap.containsValue(cluster)) {
            return false;// 应该抛出自定义异常；
        } else {
            this.ChildenMap.put(cluster.getEchild1(), cluster);
            this.ChildenMap.put(cluster.getEchild2(), cluster);
            return true;
        }
    }

    /**
     * 往缓存中注册聚类的父节点
     *
     * @param cluster 聚类父节点
     * @return true 表明删除成功 <br> false 表明删除失败 <br>
     */
    public boolean registerParent(IACluster cluster) {
        if (this.ParentMap.containsValue(cluster)) {
            return false;// 应该抛出自定义异常；
        } else {
            this.ParentMap.put(cluster.getEparent(), cluster);
            return true;
        }
    }

    /**
     * 移除缓存中所有的聚类<br> 移除数据库中的聚类<br>
     */
    public void removeAllCluster() {
        if (this.ChildenMap != null) {
            this.ChildenMap.clear();

        } else if (this.ParentMap != null) {
            this.ParentMap.clear();
        }
        this.IDALfactory.CreateDataProcess().removeAllCluster();
    }

    /**
     * 获取缓存中最小父节点ID
     *
     * @return 父节点ID
     */
    public int getMinParent() {
        return this.ParentMap.firstKey();
    }

    /**
     * 获取缓存聚类子节点
     *
     * @param HID 子节点ID
     * @return 聚类子节点
     */
    public IACluster getChildren(int HID) {
        return this.ChildenMap.get(HID);
    }

    /**
     * 将所有缓存中的聚类结果，推送至数据库中
     */
    public void PushClusterIntoDB() {
        IDALfactory.CreateDataProcess().PushClusterIntoDB(ParentMap);
    }

    /**
     * 获取父节点
     *
     * @param HID 父节点ID
     * @return 父节点
     */
    public IACluster getParent(int HID) {
        return this.ParentMap.get(HID);
    }

    /**
     * 更新缓存中的房屋实体
     *
     * @param house 房屋实体
     * @return true 表明删除成功 <br> false 表明删除失败 <br>
     */
    public boolean updataHouse(IAHouse house) {
        if (this.HouseMap.containsKey(house.getObjectID())) {
            this.HouseMap.remove(house.getObjectID());
            this.HouseMap.put(house.getObjectID(), house);
            return true;
        } else {
            return false;
        }
    }
}
